package com.ttg.security;

//~--- non-JDK imports --------------------------------------------------------

import com.ttg.utils.Assert;
import org.apache.commons.codec.digest.DigestUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;

//~--- JDK imports ------------------------------------------------------------

//~--- classes ----------------------------------------------------------------

/**
 * Class EncryptionUtils
 * Description
 * Create 2016-02-25 01:06:30 
 * @author Ardy    
 */
public class EncryptionUtils {

    /** 
     * Field CERTIFICATE_TYPE
     * Description 
     */
    public static final String CERTIFICATE_TYPE = "X.509";

    /**
     * Method md5 
     * Description 说明：
     *
     * @param text 说明：
     * @param charset 说明：
     *
     * @return 返回值说明：
     */
    public static String md5(String text, String charset) {
        return DigestUtils.md5Hex(getContentBytes(text, charset));
    }

    /**
     * Method getContentBytes 
     * Description 说明：
     *
     * @param content 说明：
     * @param charset 说明：
     *
     * @return 返回值说明：
     */
    private static byte[] getContentBytes(String content, String charset) {
        Assert.hasText(charset);

        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException var3) {
            throw new IllegalArgumentException("The Character Encoding[" + charset + "] is not supported!");
        }
    }

    /**
     * Method signByX509Certificate 
     * Description 说明：
     *
     * @param keystoreType 说明：
     * @param data 说明：
     * @param keyStorePath 说明：
     * @param keyStorePassword 说明：
     * @param alias 说明：
     * @param keyPassword 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static byte[] signByX509Certificate(String keystoreType, byte[] data, String keyStorePath,
            char[] keyStorePassword, String alias, char[] keyPassword)
            throws Exception {
        KeyStore ks = loadKeyStore(keyStorePath, keyStorePassword, keystoreType);

        if (alias == null) {
            ArrayList x509Certificate = Collections.list(ks.aliases());

            if (x509Certificate.size() != 1) {
                throw new IllegalArgumentException(
                    "[Assertion failed] - this String argument[alias] must have text; it must not be null, empty, or blank");
            }

            alias = (String) x509Certificate.get(0);
        }

        X509Certificate x509Certificate1 = (X509Certificate) ks.getCertificate(alias);
        Signature       signature        = Signature.getInstance(x509Certificate1.getSigAlgName());
        PrivateKey      privateKey       = (PrivateKey) ks.getKey(alias, keyPassword);

        signature.initSign(privateKey);
        signature.update(data);

        return signature.sign();
    }

    /**
     * Method signByX509Certificate 
     * Description 说明：
     *
     * @param data 说明：
     * @param x509Certificate 说明：
     * @param privateKey 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static byte[] signByX509Certificate(byte[] data, X509Certificate x509Certificate, PrivateKey privateKey)
            throws Exception {
        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());

        signature.initSign(privateKey);
        signature.update(data);

        return signature.sign();
    }

    /**
     * Method getCertificate 
     * Description 说明：
     *
     * @param certificateContent 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static Certificate getCertificate(byte[] certificateContent) throws Exception {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(certificateContent);
        Certificate          var4;

        try {
            CertificateFactory cf   = CertificateFactory.getInstance("X.509");
            Certificate        cert = cf.generateCertificate(inputStream);

            var4 = cert;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }

        return var4;
    }

    /**
     * Method getPrivateKeyByKeyStore 
     * Description 说明：
     *
     * @param keystoreType 说明：
     * @param keyStorePath 说明：
     * @param keyStorePassword 说明：
     * @param alias 说明：
     * @param keyPassword 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static PrivateKey getPrivateKeyByKeyStore(String keystoreType, String keyStorePath, char[] keyStorePassword,
            String alias, char[] keyPassword)
            throws Exception {
        KeyStore ks = loadKeyStore(keyStorePath, keyStorePassword, keystoreType);

        if (alias == null) {
            ArrayList key = Collections.list(ks.aliases());

            if (key.size() != 1) {
                throw new IllegalArgumentException(
                    "[Assertion failed] - this String argument[alias] must have text; it must not be null, empty, or blank");
            }

            alias = (String) key.get(0);
        }

        PrivateKey key1 = (PrivateKey) ks.getKey(alias, keyPassword);

        return key1;
    }

    /**
     * Method loadKeyStore 
     * Description 说明：
     *
     * @param keyStorePath 说明：
     * @param password 说明：
     * @param keystoreType 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static KeyStore loadKeyStore(String keyStorePath, char[] password, String keystoreType) throws Exception {
        KeyStore ks       = KeyStore.getInstance(( keystoreType == null ) ? KeyStore.getDefaultType() : keystoreType);
        File     keystore = new File(keyStorePath);

        if (( keystore == null ) || ( keystore.exists() && keystore.isDirectory() )) {
            throw new IllegalArgumentException("keystore[" + keyStorePath + "]必须是一个已经存在的文件,不能为空,且不能是一个文件夹");
        } else {
            FileInputStream is = null;
            KeyStore        var6;

            try {
                is = new FileInputStream(keystore);
                ks.load(is, password);
                var6 = ks;
            } finally {
                if (is != null) {
                    is.close();
                }
            }

            return var6;
        }
    }

    /**
     * Method getCertificate 
     * Description 说明：
     *
     * @param certificatePath 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static Certificate getCertificate(String certificatePath) throws Exception {
        File certificate = new File(certificatePath);

        if (( certificate != null ) && ( !certificate.exists() ||!certificate.isDirectory() )) {
            FileInputStream inputStream = null;
            Certificate     var5;

            try {
                inputStream = new FileInputStream(certificate);

                CertificateFactory cf   = CertificateFactory.getInstance("X.509");
                Certificate        cert = cf.generateCertificate(inputStream);

                var5 = cert;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
            }

            return var5;
        } else {
            throw new IllegalArgumentException("certificatePath[" + certificatePath + "]必须是一个已经存在的文件,不能为空,且不能是一个文件夹");
        }
    }

    /**
     * Method getCertificate 
     * Description 说明：
     *
     * @param keystoreType 说明：
     * @param keyStorePath 说明：
     * @param keyStorePassword 说明：
     * @param alias 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static Certificate getCertificate(String keystoreType, String keyStorePath, char[] keyStorePassword,
            String alias)
            throws Exception {
        KeyStore ks = loadKeyStore(keyStorePath, keyStorePassword, keystoreType);

        if (alias == null) {
            ArrayList aliases = Collections.list(ks.aliases());

            if (aliases.size() != 1) {
                throw new IllegalArgumentException(
                    "[Assertion failed] - this String argument[alias] must have text; it must not be null, empty, or blank");
            }

            alias = (String) aliases.get(0);
        }

        return ks.getCertificate(alias);
    }

    /**
     * Method getSignature 
     * Description 说明：
     *
     * @param keystoreType 说明：
     * @param keyStorePath 说明：
     * @param keyStorePassword 说明：
     * @param alias 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static Certificate getSignature(String keystoreType, String keyStorePath, char[] keyStorePassword,
            String alias)
            throws Exception {
        KeyStore ks = loadKeyStore(keyStorePath, keyStorePassword, keystoreType);

        if (alias == null) {
            ArrayList aliases = Collections.list(ks.aliases());

            if (aliases.size() != 1) {
                throw new IllegalArgumentException(
                    "[Assertion failed] - this String argument[alias] must have text; it must not be null, empty, or blank");
            }

            alias = (String) aliases.get(0);
        }

        return ks.getCertificate(alias);
    }

    /**
     * Method verifySign 
     * Description 说明：
     *
     * @param data 说明：
     * @param sign 说明：
     * @param keystoreType 说明：
     * @param keyStorePath 说明：
     * @param keyStorePassword 说明：
     * @param alias 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static boolean verifySign(byte[] data, byte[] sign, String keystoreType, String keyStorePath,
                                     char[] keyStorePassword, String alias)
            throws Exception {
        X509Certificate certificate = (X509Certificate) getCertificate(keystoreType, keyStorePath, keyStorePassword,
                                          alias);
        Signature signature = Signature.getInstance(certificate.getSigAlgName());

        signature.initVerify(certificate);
        signature.update(data);

        return signature.verify(sign);
    }

    /**
     * Method verifySign 
     * Description 说明：
     *
     * @param data 说明：
     * @param sign 说明：
     * @param x509certificate 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static boolean verifySign(byte[] data, byte[] sign, X509Certificate x509certificate) throws Exception {
        Signature signature = Signature.getInstance(x509certificate.getSigAlgName());

        signature.initVerify(x509certificate);
        signature.update(data);

        return signature.verify(sign);
    }

    /**
     * Method verifySign 
     * Description 说明：
     *
     * @param data 说明：
     * @param sign 说明：
     * @param certificatePath 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static boolean verifySign(byte[] data, byte[] sign, String certificatePath) throws Exception {
        X509Certificate certificate = (X509Certificate) getCertificate(certificatePath);
        Signature       signature   = Signature.getInstance(certificate.getSigAlgName());

        signature.initVerify(certificate);
        signature.update(data);

        return signature.verify(sign);
    }

    public static void main(String[] args) {
        try {
            boolean flag = verifySign("merOrderId=2016083017020145819&merchantId=5cf5ac3965c4ddce&orderCompleteTime=2016-08-30 16:57:21&orderCreateTime=2016-08-30 16:56:04&payAccount=6221558812340000&payStatus=1001&transAmt=1".getBytes(),"B2xqj6e+FtoIoQV8WSBuEyTEwJQ+LHOhl6VHjIphQI0YdMbMKYxRqfHjf0Z9lt4t/eXty3C+9bQIOZ7GvXy5jpHgWpJxXRDrZ8iHuu43PclZW481t6UdyaCtCV3b5FwwjMB7oUr4LSQSMAyIQw7bopZzxBdSHQQZJNumLOITE30=".getBytes(),"D:\\conf\\mock.cer");
            System.out.println(flag);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Method verifySign 
     * Description 说明：
     *
     * @param data 说明：
     * @param sign 说明：
     * @param certificateContent 说明：
     *
     * @return 返回值说明：
     *
     * @throws Exception 异常：
     */
    public static boolean verifySign(byte[] data, byte[] sign, byte[] certificateContent) throws Exception {
        X509Certificate certificate = (X509Certificate) getCertificate(certificateContent);
        Signature       signature   = Signature.getInstance(certificate.getSigAlgName());

        signature.initVerify(certificate);
        signature.update(data);

        return signature.verify(sign);
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
